package com.framework.service.system.impl;

import com.framework.common.exception.login.LoginFailLimitException;
import com.framework.common.model.response.R;
import com.framework.common.util.encrypt.MD5Util;
import com.framework.common.util.encrypt.PasswordUtil;
import com.framework.common.util.encrypt.RSAEncrypt;
import com.framework.common.util.other.NumeralUtil;
import com.framework.common.util.other.UUIDUtil;
import com.framework.common.util.redis.RedisKeyUtil;
import com.framework.mapper.system.SystemUserMapper;
import com.framework.model.system.vo.SystemUserVo;
import com.framework.service.base.BaseService;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.framework.service.system.SystemUserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.session.FindByIndexNameSessionRepository;
import org.springframework.session.Session;
import org.springframework.session.data.redis.RedisIndexedSessionRepository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * @author 龘鵺
 * @version 1.0
 * @className com.framework.service.system.impl.SystemUserServiceImpl
 * @description 用户管理业务接口实现类
 * @datetime 2024-06-19 09:34:28
 */
@Service("systemUserServiceImpl")
public class SystemUserServiceImpl extends BaseService implements SystemUserService {
    private Logger log = LoggerFactory.getLogger(SystemUserServiceImpl.class);
    @Autowired
    private SystemUserMapper systemUserMapper;
    @Autowired
    private FindByIndexNameSessionRepository<? extends Session> sessionRepository;
    @Autowired
    private RedisIndexedSessionRepository redisIndexedSessionRepository;

    /**
     * @param id 1 编号
     * @return com.framework.model.system.vo.SystemUserVo
     * @title 根据编号查询用户管理
     * @description 根据编号查询用户管理
     * @author 龘鵺
     * @datetime 2024-06-19 09:34:28
     * @version 1.0
     */
    @Override
    public SystemUserVo getByIdParam(Long id) {
        SystemUserVo row = new SystemUserVo();
        row.setId(id);
        row.setGtaeOperaterStatus(NumeralUtil.POSITIVE_ONE);
        SystemUserVo p = systemUserMapper.selectByParam(row);
        if (p == null) {
            return new SystemUserVo();
        }
        p.setPassword(null);
        return p;
    }

    /**
     * @param row 1 用户管理类
     * @return com.framework.common.model.response.R
     * @title 新增用户管理
     * @description 新增用户管理
     * @author 龘鵺
     * @datetime 2024-06-19 09:34:28
     * @version 1.0
     */
    @Override
    @Transactional
    public R<?> save(SystemUserVo row) {
        try {
            row.setPassword(RSAEncrypt.decryptPrivate(row.getPassword(), PasswordUtil.privateKey));
            row.setConfirmPassword(RSAEncrypt.decryptPrivate(row.getConfirmPassword(), PasswordUtil.privateKey));
        } catch (Exception e) {
            log.error("save:解密错误:{}", row.getAccount());
            throw new LoginFailLimitException("解密错误！");
        }
        if (row.getPassword().length() < NumeralUtil.POSITIVE_SIX || row.getPassword().length() > NumeralUtil.POSITIVE_TWENTY_FIVE) {
            return R.fail("密码最少6至最多25个字符！");
        }
        if (!row.getPassword().equals(row.getConfirmPassword())) {
            return R.fail("两次密码不相同！");
        }
        row.setPage(NumeralUtil.POSITIVE_ONE);
        row.setLimit(NumeralUtil.POSITIVE_ONE);
        int num = systemUserMapper.isExist(row);
        if (num > NumeralUtil.POSITIVE_ZERO) {
            return R.fail();
        }
        String salt = UUIDUtil.getUUID();
        SystemUserVo systemUserVo = getUser();
        String password = MD5Util.MD5EncodeToPassword(row.getPassword(), salt);
        row.setPassword(password);
        Date date = new Date();
        Long userId = systemUserVo.getId();
        row.setOperaterTime(date);
        row.setOperaterStatus(NumeralUtil.POSITIVE_ONE);
        row.setCreateId(userId);
        row.setOperaterId(userId);
        row.setCreateTime(date);
        row.setSalt(salt);
        if (systemUserVo.getUserLevel() != null) {
            row.setUserLevel(systemUserVo.getUserLevel().intValue() + NumeralUtil.POSITIVE_ONE);
        } else {
            row.setUserLevel(NumeralUtil.POSITIVE_TWO);
        }
        systemUserMapper.insertSelective(row);
        return R.ok();
    }

    /**
     * @param row 1 用户管理类
     * @return com.framework.common.model.response.R
     * @title 编辑用户管理
     * @description 编辑用户管理
     * @author 龘鵺
     * @datetime 2024-06-19 09:34:28
     * @version 1.0
     */
    @Override
    @Transactional
    public R<?> edit(SystemUserVo row) {
        SystemUserVo su = this.selectByMap(row.getId());
        if (su == null) {
            return R.fail("修改用户信息不存在!");
        }
//        if (StringUtils.isNotEmpty(row.getPassword())) {
//            if (row.getPassword().length() < NumeralUtil.POSITIVE_SIX || row.getPassword().length() > NumeralUtil.POSITIVE_TWENTY_FIVE) {
//                return R.fail("密码最少6至最多25个字符");
//            }
//            if (!row.getPassword().equals(row.getConfirmPassword())) {
//                return R.fail("两次密码不相同！");
//            }
//            String password = MD5Util.MD5EncodeToPasswordBack(row.getPassword());
//            if (su.getPassword().equals(password)) {
//                return R.fail("新旧密码不能相同!");
//            }
//            row.setPassword(password);
//        }
        //禁用后踢出用户
        if (row.getEnableStatus().intValue() == NumeralUtil.POSITIVE_TWO) {
            // 查询用户的 Session 信息，返回值 key 为 sessionId
            Map<String, ? extends Session> userSessions = sessionRepository.findByIndexNameAndIndexValue(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME, su.getAccount());
            if (userSessions.size() > NumeralUtil.POSITIVE_ZERO) {
                // 移除用户的 session 信息
                Set<String> sessionIds = userSessions.keySet();
                if (sessionIds.size() > NumeralUtil.POSITIVE_ZERO) {
                    for (String session : sessionIds) {
                        redisIndexedSessionRepository.deleteById(session);
                    }
                }
            }
        }
        SystemUserVo systemUserVo = getUser();
        if (row.getUserLevel() == null) {
            row.setUserLevel(su.getUserLevel());
        } else {
            if (systemUserVo.getUserLevel().intValue() >= row.getUserLevel()) {
                return R.fail("当前修改级别不能大于登录帐号级别");
            }
        }
        row.setSalt(null);
        row.setAccount(null);
        Date date = new Date();
        Long userId = getUserId();
        row.setOperaterId(userId);
        row.setOperaterTime(date);
        row.setOperaterStatus(NumeralUtil.POSITIVE_TWO);
        row.setPassword(null);
        systemUserMapper.updateByPrimaryKeySelective(row);
        return R.ok();
    }

    /**
     * @param id 1 编号
     * @return com.framework.common.model.response.R
     * @title 删除用户管理
     * @description 删除用户管理
     * @author 龘鵺
     * @datetime 2024-06-19 09:34:28
     * @version 1.0
     */
    @Override
    @Transactional
    public R<?> delete(Long id) {
        SystemUserVo SystemUserVo = getUser();
        Long userId = SystemUserVo.getId();
        Date date = new Date();
        SystemUserVo row = new SystemUserVo();
        row.setOperaterStatus(NumeralUtil.NEGATIVE_ONE);
        row.setOperaterTime(date);
        row.setOperaterId(userId);
        row.setId(id);
        systemUserMapper.delete(row);
        return R.ok();
    }

    /**
     * @param idList 1 编号集合
     * @return com.framework.common.model.response.R
     * @title 批量删除用户管理
     * @description 批量删除用户管理
     * @author 龘鵺
     * @datetime 2024-06-19 09:34:28
     * @version 1.0
     */
    @Override
    @Transactional
    public R<?> batchDeleteList(List<Long> idList) {
        if (idList == null || idList.size() < NumeralUtil.POSITIVE_ONE) {
            return R.fail();
        }
        Date date = new Date();
        SystemUserVo row = new SystemUserVo();
        row.setIdList(idList);
        row.setOperaterStatus(NumeralUtil.NEGATIVE_ONE);
        row.setOperaterTime(date);
        Long userId = getUserId();
        row.setOperaterId(userId);
        systemUserMapper.deleteList(row);
        return R.ok();
    }

    /**
     * @param row 1 用户管理类
     * @return java.util.List<com.framework.model.system.vo.SystemUserVo>
     * @title 查询用户管理集合
     * @description 查询用户管理集合
     * @author 龘鵺
     * @datetime 2024-06-19 09:34:28
     * @version 1.0
     */
    @Override
    public List<SystemUserVo> findByList(SystemUserVo row) {
        row.setGtaeOperaterStatus(NumeralUtil.POSITIVE_ONE);
        List<SystemUserVo> list = systemUserMapper.findByList(row);
        return list;
    }

    /**
     * @param row 1 用户管理类
     * @return com.framework.common.model.response.R
     * @title 分页查询用户管理列表
     * @description 分页查询用户管理列表
     * @author 龘鵺
     * @datetime 2024-06-19 09:34:28
     * @version 1.0
     */
    @Override
    public R<?> findParamPageList(SystemUserVo row) {
        SystemUserVo systemUserVo = getUser();
        if (!super.ignoredDataRoleAuth.getAuthList().contains(systemUserVo.getRoleCode())) {
            row.setGtNum(systemUserVo.getUserLevel());
        }
        row.setGtaeOperaterStatus(NumeralUtil.POSITIVE_ONE);
        int count = systemUserMapper.findPageListCount(row);
        if (count == NumeralUtil.POSITIVE_ZERO) {
            return R.ok();
        }
        List<SystemUserVo> list = systemUserMapper.findPageList(row);
        return R.ok(list, count);
    }

    /**
     * @param id 1 编号
     * @return com.framework.model.system.vo.SystemUserVo
     * @title 公共根据编号查询数据
     * @description 公共根据编号查询数据
     * @author 龘鵺
     * @datetime 2024-06-19 09:34:28
     */
    @Override
    public SystemUserVo selectByMap(Long id) {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("id", id);
        if (getUser().getUserLevel().intValue() > NumeralUtil.POSITIVE_ZERO) {
            map.put("gtNum", getUser().getUserLevel());
        } else {
            map.put("gtaeNum", getUser().getUserLevel());
        }
        return systemUserMapper.selectByMap(map);
    }

    /**
     * @param id      1 编号
     * @param account 2 帐号
     * @return com.framework.common.model.response.R
     * @title 本类后台管理查询是否存在，只是适合本身的一些方法处理。
     * @description boolean false不存在， true存在
     * @author 龘鵺
     * @datetime 2024-06-19 09:34:28
     */
    @Override
    public R<?> isExist(Long id, String account) {
        SystemUserVo row = new SystemUserVo();
        row.setId(id);
        row.setAccount(account);
        boolean is = systemUserMapper.isExist(row) > NumeralUtil.POSITIVE_ZERO ? Boolean.FALSE : Boolean.TRUE;
        return R.ok(is);
    }

    /**
     * @param row 1 用户管理类
     * @return com.framework.common.model.response.R
     * @title 修改密码
     * @description 修改密码
     * @author 龘鵺
     * @datetime 2024-06-19 09:34:28
     */
    @Override
    public R<?> password(SystemUserVo row) {
        try {
            row.setPassword(RSAEncrypt.decryptPrivate(row.getPassword(), PasswordUtil.privateKey));
            row.setConfirmPassword(RSAEncrypt.decryptPrivate(row.getConfirmPassword(), PasswordUtil.privateKey));
        } catch (Exception e) {
            log.error("save:解密错误:{}", row.getAccount());
            throw new LoginFailLimitException("解密错误！");
        }
        if (row.getPassword().length() < NumeralUtil.POSITIVE_SIX || row.getPassword().length() > NumeralUtil.POSITIVE_TWENTY_FIVE) {
            return R.fail("密码最少6至最多25个字符！");
        }
        SystemUserVo su = this.selectByMap(row.getId());
        if (su == null) {
            return R.fail("修改用户信息不存在!");
        }
        if (!row.getPassword().equals(row.getConfirmPassword())) {
            return R.fail("两次密码不相同！");
        }
        String password = MD5Util.MD5EncodeToPassword(row.getPassword(), su.getSalt());
        if (su.getPassword().equals(password)) {
            return R.fail("新旧密码不能相同!");
        }
        SystemUserVo param = new SystemUserVo();
        Date date = new Date();
        Long userId = getUserId();
        param.setId(row.getId());
        param.setOperaterId(userId);
        param.setOperaterTime(date);
        param.setOperaterStatus(NumeralUtil.POSITIVE_TWO);
        param.setPassword(password);
        systemUserMapper.updateByPrimaryKeySelective(param);
        return R.ok();
    }

    /**
     * @param id 1 编号
     * @return com.framework.model.system.vo.SystemUserVo
     * @title 公共根据编号查询数据
     * @description 公共根据编号查询数据
     * @author 龘鵺
     * @datetime 2024-06-19 09:34:28
     */
    @Override
    public SystemUserVo selectByParam(Long id) {
        return systemUserMapper.selectByPrimaryKey(id);
    }

    /**
     * @param id 1 编号
     * @return com.framework.common.model.response.R
     * @title 根据编号查询信息
     * @description 根据编号查询信息
     * @author 龘鵺
     * @datetime 2024-06-19 09:34:28
     */
    @Override
    public R<?> getByIdInfo(Long id) {
        SystemUserVo row = this.selectByMap(id);
        if (row == null) {
            return R.ok(new SystemUserVo());
        }
        row.setPassword(null);
        return R.ok(row);
    }

    /**
     * @param account 1 帐号
     * @return com.framework.model.system.vo.SystemUserVo
     * @title 登录查询
     * @description 登录查询
     * @author 龘鵺
     * @datetime 2024-06-19 09:34:28
     */
    @Override
    public SystemUserVo queryForLoginName(String account) {
        return systemUserMapper.queryForLoginName(account);
    }

    /**
     * @return boolean
     * @title 验证用户是否为超级管理员权限
     * @description 验证用户是否为超级管理员权限
     * @author 龘鵺
     * @datetime 2024-06-19 09:34:28
     */
    @Override
    public boolean isAuth() {
        SystemUserVo su = super.getUser();
        return super.ignoredRoleAuth.getAuthList().contains(su.getRoleCode());
    }

    /**
     * @param id 1 编号
     * @return com.framework.common.model.response.R
     * @title 启用|禁用，用户
     * @description 启用|禁用，用户
     * @author 龘鵺
     * @datetime 2024-06-19 09:34:28
     * @version 1.0
     */
    @Override
    @Transactional
    public R<?> enable(Long id) throws Exception {
        String timeKey = RedisKeyUtil.getObjKey("SYSTEM_USER_ENABLE_KEY", "SYSTEM_USER_ENABLE_KEY", id.toString());
        long expireNum = redisUtil.getExpire(timeKey);
        if (expireNum > NumeralUtil.POSITIVE_ZERO) {
            return R.fail("操作频繁,请" + expireNum + "秒后重试!");
        }
        SystemUserVo row = new SystemUserVo();
        SystemUserVo systemUserVo = getUser();
        Long userId = systemUserVo.getId();
        row.setId(id);
        row.setGtaeOperaterStatus(NumeralUtil.POSITIVE_ZERO);
        row = systemUserMapper.selectByParam(row);
        if (row == null) {
            return R.fail("信息不存在!");
        }
        redisUtil.setString(timeKey, NumeralUtil.STRING_POSITIVE_ZERO, NumeralUtil.POSITIVE_THIRTY);
        Date date = new Date();
        SystemUserVo updateRow = new SystemUserVo();
        updateRow.setId(id);
        updateRow.setOperaterId(userId);
        updateRow.setOperaterTime(date);
        updateRow.setOperaterStatus(NumeralUtil.POSITIVE_TWO);
        updateRow.setEnableStatus(row.getEnableStatus().intValue() == NumeralUtil.POSITIVE_TWO ? NumeralUtil.POSITIVE_ONE : NumeralUtil.POSITIVE_TWO);
        int enableStatusNum = systemUserMapper.updateByPrimaryKeySelective(updateRow);
        if (enableStatusNum > NumeralUtil.POSITIVE_ZERO && updateRow.getEnableStatus().intValue() == NumeralUtil.POSITIVE_TWO) {
            // 查询用户的 Session 信息，返回值 key 为 sessionId
            Map<String, ? extends Session> userSessions = sessionRepository.findByIndexNameAndIndexValue(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME, row.getAccount());
            if (userSessions.size() > NumeralUtil.POSITIVE_ZERO) {
                // 移除用户的 session 信息
                Set<String> sessionIds = userSessions.keySet();
                if (sessionIds.size() > NumeralUtil.POSITIVE_ZERO) {
                    for (String session : sessionIds) {
                        redisIndexedSessionRepository.deleteById(session);
                    }
                }
            }
        }
        return R.ok();
    }

}